/****************************************
 * create by:  iodevice.cpp
 * Date:    2020-09-23
 * Description: 将设备硬件操作相关的放到此模块
 ***************************************/
#include "iodevice.h"
struct nvm_data_str nvm_data[4];

/************************************************************************
* 函数名称: nvm_save()
* 输入参数: 无
* 返回值  : 无
* 功    能: 指示灯控制
**********************************************************************/
void nvm_save(struct nvm_data_str *nvm_d)
{
    if (nvm_d->offset < 4096)
    {
        FLASH_WRITE(((nvm_d->start_sec) << 12) + nvm_d->offset, &nvm_d->value, 4);
        nvm_d->offset += 4;
    }
    else
    {
        FLASH_ERASE_PAGE(nvm_d->start_sec + 1);
        FLASH_WRITE((nvm_d->start_sec + 1) << 12, &nvm_d->value, 4);
        FLASH_ERASE_PAGE(nvm_d->start_sec);
        nvm_d->offset = 4;
        FLASH_WRITE((nvm_d->start_sec) << 12, &nvm_d->value, 4);
    }
}
/******************************************************************************
 * FunctionName : nvm_load
 * Description  : 加载NVM数据
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void nvm_load(struct nvm_data_str *nvm_d)
{
    uint32_t value;
    for (nvm_d->offset = 0; nvm_d->offset < 4096;)
    {
        FLASH_READ(((nvm_d->start_sec) << 12) + nvm_d->offset, &value, 4);
        if (value != 0xffffffff)
        {
            nvm_d->value = value;
            nvm_d->offset += 4;
        }
        else
        {
            break;
        }
    }
    if (nvm_d->offset == 0)
    {
        FLASH_ERASE_PAGE(nvm_d->start_sec);
        FLASH_READ((nvm_d->start_sec + 1) << 12, &value, 4);
        if (value != 0xffffffff)
        {
            nvm_d->value = value;
        }
        else
        {
            nvm_d->value = 0;
        }
    }
}

void nvm_datainit(void)
{
    nvm_data[NVM_RUNT].start_sec = NVM_START_ADDR + (NVM_RUNT << 1);
    nvm_load(&nvm_data[NVM_RUNT]);
    Serial.printf("NVM_RUNT:%d\n", nvm_data[NVM_RUNT].value);
    nvm_data[NVM_WORKT].start_sec = NVM_START_ADDR + (NVM_WORKT << 1);
    nvm_load(&nvm_data[NVM_WORKT]);
    Serial.printf("NVM_WORKT:%d\n", nvm_data[NVM_WORKT].value);
    nvm_data[NVM_STAS].start_sec = NVM_START_ADDR + (NVM_STAS << 1);
    nvm_load(&nvm_data[NVM_STAS]);
    Serial.printf("NVM_STAS:%d\n", nvm_data[NVM_STAS].value);
    nvm_data[NVM_LDNUM].start_sec = NVM_START_ADDR + (NVM_LDNUM << 1);
    nvm_load(&nvm_data[NVM_LDNUM]);
    Serial.printf("NVM_LDNUM:%d\n", nvm_data[NVM_LDNUM].value);
}

void system_param_save(void)
{
    FLASH_ERASE_PAGE((SYSTEM_PAR_ADDR) >> 12);
    FLASH_WRITE(SYSTEM_PAR_ADDR, (uint32_t *)&system_par, sizeof(system_par));
}

void system_param_load(void)
{
    FLASH_READ(SYSTEM_PAR_ADDR, (uint32_t *)&system_par, sizeof(system_par));
    if ((system_par.start != 0x55aaaa55) || (system_par.end != 0x55aaaa55))
    {
        system_par.start = 0x55aaaa55;
        system_par.end = 0x55aaaa55;
        system_param_save();
    }
}

/************************************************************************
* 函数名称: pilot_set()
* 输入参数: 无
* 返回值  : 无
* 功    能: 指示灯控制
**********************************************************************/
void pilot_set(char stas, char c)
{
    if (stas == 0)
    {
        digitalWrite(pilot_pin, LOW);
    }
    else
    {
        digitalWrite(pilot_pin, HIGH);
    }
}
/************************************************************************
* 函数名称: pilot_set()
* 输入参数: 无
* 返回值  : 无
* 功    能: 指示灯控制
**********************************************************************/
void out_set(char stas, char ch)
{
    pilot_set(stas, 0);
    if (stas == 0)
    {
        digitalWrite(out_pin,LOW);
    }
    else
    {
        digitalWrite(out_pin, HIGH);
    }

#if DEVTYPE == TYPE_RGB
    argb_set(stas);
#endif
}
/************************************************************************
* 函数名称: argb_set()
* 输入参数: 无
* 返回值  : 无
* 功    能: 对于彩灯设置rgb输出，目前只是调节显示亮度
**********************************************************************/
void argb_set(uint32_t argb)
{
    unsigned char a = argb >> 24;
    unsigned char r = (argb >> 16) & 0xff;
    unsigned char g = (argb >> 8) & 0xff;
    unsigned char b = (argb >> 0) & 0xff;
    Serial.printf("argb:%x",argb);
    analogWriteFreq(1000);
    analogWriteRange(255);
    if (a)
    {
        analogWrite(blue_pin, b);  //模拟信号输出
        analogWrite(red_pin, r);   //模拟信号输出
        analogWrite(green_pin, g); //模拟信号输出
        
    }
    else
    {
        analogWrite(blue_pin, 0);  //模拟信号输出
        analogWrite(red_pin, 0);   //模拟信号输出
        analogWrite(green_pin, 0); //模拟信号输出
    }
}

/************************************************************************
* 函数名称: DEV_Init()
* 输入参数: 无
* 返回值  : 无
* 功    能: 设备初始化
**********************************************************************/
void DEV_Init(void)
{
    pinMode(pilot_pin, OUTPUT);
    pinMode(blue_pin, OUTPUT);
    pinMode(red_pin, OUTPUT);
    pinMode(green_pin, OUTPUT);
    gpio_dev_init();
}

/************************************************************************
* 函数名称: DEV_Loop()
* 输入参数: 无
* 返回值  : 无
* 功    能: 主循环调用
**********************************************************************/
void DEV_Loop(void)
{
    static unsigned long last_time = millis();
    if (millis() - last_time > 100) //100ms时钟控制
    {
        last_time = millis();
        gpio_dev_tick(NULL);
    }
}